class Heart {
  // 自定义的socket封装对象
  mySocket = null;
  // 0 啥也没做
  // 1 发送了ping信号
  // 2 接受到了pong信号
  flag = 0;
  // ping和pong的定时器
  pingTimer = null;
  pongTimer = null;

  constructor(mySocket) {
    this.mySocket = mySocket;
  }

  /* 
  接收pong信号, 改变标识状态, 如果标识不正确, 停止心跳, 重新连接
  */
  getPong = (e) => {
    if (e.data === "pong") {
      if (this.flag === 1) {
        this.flag = 2;
      } else {
        // 出现问题
        this.stop();
      }
    }
  };

  // 开始心跳检测
  start() {
    // 绑定消息监听, 接收pong信号
    this.mySocket.ws.addEventListener("message", this.getPong);
    // 准备开始发送ping信号
    this.startPing();
  }

  /* 
  开始向服务器发送ping消息
  */
  startPing() {
    // 启动定时器发送ping消息
    this.pingTimer = setTimeout(() => {
      if (this.flag === 0) {
        this.flag = 1;
        console.log('发送心跳检查消息');
        this.mySocket.ws.send("ping");
      } else { // 出现问题
        this.stop();
        this.mySocket.init()
        return;
      }

      // 规定时间内接受服务器返回pong信号，才能确定连接没有问题
      this.pongTimer = setTimeout(() => {
        // 如果pong已经到位了, 再次启动一个新的跳转
        if (this.flag === 2) {
          this.flag = 0;
          this.startPing()
        } else {  // 否则出现问题, 停止心跳检测
          this.stop();
          this.mySocket.init()
        }
      }, 2000);
    }, 5000);
  }

  /* 
  停止心跳检测
  */
  stop() {
    // 重置flag
    this.flag = 0;
    // 清除ping和pong的定时器
    clearTimeout(this.pingTimer);
    clearTimeout(this.pongTimer);
    // 移除接收消息的监听
    this.mySocket.ws.removeEventListener("message", this.getPong);
    // 判断socket连接
    this.mySocket.ws.close();
  }
}

class MySocket {
  // socket对象
  ws = null;
  // 心跳检测对象
  heart = null;
  // 重连次数
  repeatCount = 0;
  // 最大重连次数
  maxRepeatCount = 3;
  // 重连的定时器
  timer = null;
  // 接收消息的回调函数(由组件指定)
  cb = null;

  lockRepeat = false

  constructor(cb) {
    this.cb = cb
    this.init();
  }

  /* 
  创建websocket连接, 并绑定连接成功和失败的监听
  */
  init() {
    // this.ws = new WebSocket("ws://localhost:8899");
    this.ws = new WebSocket("ws://43.156.99.190:8088/");
    this.ws.onopen = () => {
      this.openHandler();
    };
    this.ws.onclose = () => {
      this.closeHandler();
    };
  }

  /* 
  连接成功的回调
  */
  openHandler() {
    // 绑定接收消息监听(用于组件接收列表数据)
    this.ws.addEventListener('message', this.cb)
    clearTimeout(this.timer);
    this.repeatCount = 0;
    // 创建并启动心跳检查对象
    this.heart = new Heart(this);
    this.heart.start();
  }

  /* 
  连接失败的回调
  */
  closeHandler() {
    if (this.lockRepeat) return
    this.lockRepeat = true
    // 连接数量加1
    this.repeatCount++;
    // 移除消息监听
    this.ws.removeEventListener('message', this.cb)
    // 关闭心跳检测
    this.heart.stop()
    clearTimeout(this.timer);
    // 如果连接次数大于了最大值
    if (this.repeatCount > this.maxRepeatCount) {
      // 提示错误, 并结束
      alert("连接ws失败, 请稍后刷新试试");
      return;
    }
    console.log("重连", this.repeatCount);
    
    // 1秒后再重新连接
    this.timer = setTimeout(() => {
      this.lockRepeat = false
      this.init();
    }, 1000);
  }
}

export default MySocket;
